/*
 * Copyright 2006 Brian Watkins
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */


package bw.weather;

import java.util.*;
import bw.util.*;
import bw.os.*;

public class WeatherManager
{
    private static final String CURRENT_LOC_KEY = "WM_CURRENT_LOC";
    private static final String LOCATIONS_KEY = "WM_LOCATIONS";
    private static final String NO_LOCATION_ID = "NO_LOC";

    private static WeatherManager _instance = null;
    private static Object _lock = new Object();

    private WeatherLocation _otherLocation = null;
    private ObjectStore _store = ObjectStore.getInstance();

    public static WeatherManager getInstance()
    {
        if ( _instance == null )
        {
            synchronized ( _lock )
            {
                if ( _instance == null )
                {
                    _instance = new WeatherManager();
                }
            }
        }

        return _instance;
    }

    private WeatherManager ()
    {
        //nothing
    }

    public WeatherLocation getCurrentLocation ()
    {
        return getLocationWithReportById( getCurrentLocationId() );
    }

    public String getCurrentLocationId ()
    {
        String l = null;
        try
        {
            l = (String) _store.get( CURRENT_LOC_KEY );
        }
        catch ( Exception ex ) 
        {
            Log.getInstance().write( "Problem getting current weather location!", ex );
            l = NO_LOCATION_ID;
        }

        if ( l == null )
        {
            WeatherLocation loc = (WeatherLocation) locations().firstElement();
            l = loc.getLocationId();
        }

        return l;
    }

    public void setCurrentLocationId ( String s )
    {
        try
        {
            _store.put( CURRENT_LOC_KEY, s ); 
        }
        catch ( Exception ex )
        {
            Log.getInstance().write( "Problem storing location id!", ex );
        }
    }

    public void addLocation ( WeatherLocation loc )
    {
        locations().addElement( loc );
        syncChanges();
    }

    public void removeLocation ( WeatherLocation loc )
    {
        locations().removeElement( loc );
        syncChanges();
    }

    public void addOtherLocation ( WeatherLocation o )
    {
        _otherLocation = o;
    }

    public Vector getLocations () 
    { 
        if ( !Config.isPropertyTrue( WeatherServant.DO_REFRESH ) )
        {
            //we need to manually refresh
            //Log.getInstance().write( "Manually refreshing weather current report!" );
            WeatherLocation current = getCurrentLocation();
            if ( current != null )
            {
                try
                {
                    current.updateSource();
                }
                catch ( RefresherException ex )
                {
                    //nothing
                }
            }
        }

        return locations(); 
    }

    public WeatherLocation findLocationById ( String locId )
    {
        WeatherLocation loc = null;

        if ( locId != null && locId != NO_LOCATION_ID )
        {
            for ( Enumeration e = locations().elements(); e.hasMoreElements(); )
            {
                WeatherLocation wl = (WeatherLocation) e.nextElement();
                if ( wl.getLocationId().equals( locId ) )
                {
                    loc = wl;
                    break;
                }
            }
        }

        return loc;
    }

    public WeatherLocation getLocationWithReportById ( String locId )
    {
        WeatherLocation loc = findLocationById( locId );
        
        if ( loc != null )
        {
            //if this isn't the current location then we'll
            //fetch its report now. Only the current location is
            //fetched periodically in the background. 
            if ( !getCurrentLocationId().equals( locId ) || loc.getReport() == null )
            {
                try
                {
                    loc.updateSource();
                }
                catch ( RefresherException ex ) 
                { 
                    WeatherReport report = new WeatherReport();
                    report.setError( ex.getMessage() );
                    loc.setReport( report );
                }

                //then set it to the current location
                setCurrentLocationId( locId );
            }
        }
        
        return loc;
    }

    public WeatherLocation getOtherLocationWithReport ( String locId )
    {
        try
        {
            _otherLocation.setLocationId( locId );
            _otherLocation.updateSource();
        }
        catch ( InvalidWeatherLocationException iwl )
        {
            WeatherReport report = new WeatherReport();
            report.setError( "Invalid Location" );
            _otherLocation.setReport( report );
        }
        catch ( RefresherException ex ) 
        { 
            WeatherReport report = new WeatherReport();
            report.setError( ex.getMessage() );
            _otherLocation.setReport( report );
        }
            
        return _otherLocation;
    }

    private Vector locations ()
    {
        Vector l = null;
        try
        {
            l = (Vector) _store.get( LOCATIONS_KEY );

            if ( l == null )
            {
                l = new Vector();
                _store.put( LOCATIONS_KEY, l );
            }
        }
        catch ( Exception ex )
        {
            Log.getInstance().write( "Problem getting weather locations!", ex );
        }

        return l;
    }

    private void syncChanges ()
    {
        try
        {
            _store.sync( LOCATIONS_KEY );
        }
        catch ( Exception ex )
        {
            Log.getInstance().write( "Problem syncing changes in WeatherManager!", ex );
        }
    }
}